{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;\f2\fswiss\fcharset77 Helvetica-Oblique;
\f3\fnil\fcharset77 Monaco;}
{\colortbl;\red255\green255\blue255;\red136\green19\blue80;\red108\green5\blue64;\red64\green0\blue128;
\red255\green0\blue0;\red118\green15\blue80;\red118\green15\blue21;\red0\green51\blue105;}
\margl1440\margr1440\vieww12260\viewh8720\viewkind0
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural

\f0\b\fs28 \cf0 NOTE: This is a beta so expect everything included with beta software.\
NOTE 2: In order to install UITestingKit, put the framework in /Library/Frameworks.
\f1\b0\fs24 \
\
UITestingKit is a set of tools that allow you to write unit tests for your code and UI tests for the final application. UITestingKit (UITK) is made up of two components - a framework and a command-line app called TestsRunner. The framework contains the base classes needed to write tests while the TestsRunner is used to run the compiled tests.\
\
UITestingKit's unit testing implementation was inspired SenTestingKit. Like SenTestingKit, UITK looks for all subclasses of DPTestCase, instantiates them, and invokes all instance methods that begin with 'test'. Although the basic approach is similar there are few fundamental differences between the two kits, but before noting them it's important to understand UITK's main features.\
\
First of all, UITK was designed to support two types of testing methods - synchronized and a-synchronized testing. A synchronized test's result is known when its execution finishes (the method returns) while an async test's result is unknown on its end. Furthermore, the time when the result will be available can not be determined, and may depend on many external factors that are not directly included in the test method's logic. Synchronized testing is good for most cases, but async testing opens the possibilities of testing multi-threaded code and some simple UI logic.\
\
The second most important feature of UITK is user interface testing, or more accurately, user interaction testing. This is done by abusing Apple's accessibility API and simulating a user that operates the running application. The application's responses to the user are then monitored by QA objects that decide if testing should complete or fail. This technique will be covered later on as it's not related to unit testing and SenTestingKit.\
\
As said, like SenTestingKit, UITK identifies test methods by their name but unlike SenTestingKit, UITK also looks at the return values of these methods. UITestingKit accepts the following types: void, id, Class, BOOL and DPTestStatus (see DPTestCase.h). When UITK finds a test it must first decide if it's synchronized or not. BOOL return type is always considered synchronized and void is always async. id and Class are special types. Tests returning either id or Class separate the test's 
\f2\i action
\f1\i0  from its 
\f2\i verification
\f1\i0 . In order to better understand the concept, let's take a look at a simple example:\
\
\pard\tx480\pardeftab480\ql\qnatural\pardirnatural

\f3\fs20 \cf2 \CocoaLigature0 @interface\cf0  SimpleTest : DPTestCase\
\cf2 @end\cf0 \
\
\cf2 @implementation\cf0  SimpleTest\
\
- (\cf2 BOOL\cf0 )\cf3 testEmptyStringCreation\cf0  \{\
	\cf2 return\cf0  [[[\cf4 NSString\cf0  \cf5 alloc\cf0 ] \cf3 init\cf0 ] \cf5 autorelease\cf0 ] != \cf2 nil\cf0 ;\
\}\
\
\cf2 @end\
\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural

\f1\fs24 \cf0 \CocoaLigature1 In this example we test an empty string creation. If everything goes right then the returned string shouldn't be nil. Now, let's rewrite this example differently:
\f3\fs20 \CocoaLigature0 \
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\tx5280\tx5760\tx6240\tx6720\tx7200\tx7680\tx8160\tx8640\tx9120\tx9600\tx10080\tx10560\tx11040\tx11520\tx12000\tx12480\tx12960\tx13440\tx13920\tx14400\tx14880\tx15360\tx15840\tx16320\tx16800\tx17280\tx17760\tx18240\tx18720\tx19200\tx19680\tx20160\tx20640\tx21120\tx21600\tx22080\tx22560\tx23040\tx23520\tx24000\tx24480\tx24960\tx25440\tx25920\tx26400\tx26880\tx27360\tx27840\tx28320\tx28800\tx29280\tx29760\tx30240\tx30720\tx31200\tx31680\tx32160\tx32640\tx33120\tx33600\tx34080\tx34560\tx35040\tx35520\tx36000\tx36480\tx36960\tx37440\tx37920\tx38400\tx38880\tx39360\tx39840\tx40320\tx40800\tx41280\tx41760\tx42240\tx42720\tx43200\tx43680\tx44160\tx44640\tx45120\tx45600\tx46080\tx46560\tx47040\tx47520\tx48000\ql\qnatural\pardirnatural
\cf0 \
\cf6 @interface\cf0  SimpleTest : DPTestCase\
\cf6 @end\
\
@implementation\cf0  SimpleTest\
\
\pard\tx480\pardeftab480\ql\qnatural\pardirnatural
\cf0 - (\cf2 id\cf0 )\cf3 testEmptyStringCreation\cf0  \{\
	\cf2 return\cf0  [[[\cf4 NSString\cf0  \cf5 alloc\cf0 ] \cf3 init\cf0 ] \cf5 autorelease\cf0 ];\
\}\
\
- (\cf2 BOOL\cf0 )\cf3 verifyTestEmptyStringCreation:\cf0 (\cf4 NSString\cf0  *)retVal \{\
	\cf2 return\cf0  retVal != \cf2 nil\cf0 ;\
\}\
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\tx5280\tx5760\tx6240\tx6720\tx7200\tx7680\tx8160\tx8640\tx9120\tx9600\tx10080\tx10560\tx11040\tx11520\tx12000\tx12480\tx12960\tx13440\tx13920\tx14400\tx14880\tx15360\tx15840\tx16320\tx16800\tx17280\tx17760\tx18240\tx18720\tx19200\tx19680\tx20160\tx20640\tx21120\tx21600\tx22080\tx22560\tx23040\tx23520\tx24000\tx24480\tx24960\tx25440\tx25920\tx26400\tx26880\tx27360\tx27840\tx28320\tx28800\tx29280\tx29760\tx30240\tx30720\tx31200\tx31680\tx32160\tx32640\tx33120\tx33600\tx34080\tx34560\tx35040\tx35520\tx36000\tx36480\tx36960\tx37440\tx37920\tx38400\tx38880\tx39360\tx39840\tx40320\tx40800\tx41280\tx41760\tx42240\tx42720\tx43200\tx43680\tx44160\tx44640\tx45120\tx45600\tx46080\tx46560\tx47040\tx47520\tx48000\ql\qnatural\pardirnatural

\f1\fs24 \cf0 \CocoaLigature1 \
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\tx5280\tx5760\tx6240\tx6720\tx7200\tx7680\tx8160\tx8640\tx9120\tx9600\tx10080\tx10560\tx11040\tx11520\tx12000\tx12480\tx12960\tx13440\tx13920\tx14400\tx14880\tx15360\tx15840\tx16320\tx16800\tx17280\tx17760\tx18240\tx18720\tx19200\tx19680\tx20160\tx20640\tx21120\tx21600\tx22080\tx22560\tx23040\tx23520\tx24000\tx24480\tx24960\tx25440\tx25920\tx26400\tx26880\tx27360\tx27840\tx28320\tx28800\tx29280\tx29760\tx30240\tx30720\tx31200\tx31680\tx32160\tx32640\tx33120\tx33600\tx34080\tx34560\tx35040\tx35520\tx36000\tx36480\tx36960\tx37440\tx37920\tx38400\tx38880\tx39360\tx39840\tx40320\tx40800\tx41280\tx41760\tx42240\tx42720\tx43200\tx43680\tx44160\tx44640\tx45120\tx45600\tx46080\tx46560\tx47040\tx47520\tx48000\ql\qnatural\pardirnatural

\f3\fs20 \cf6 \CocoaLigature0 @end
\f1\fs24 \cf0 \CocoaLigature1 \
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural
\cf0 \
In the above example there's only one test method named 
\f2\i testEmptyStringCreation
\f1\i0 . The 
\f2\i testEmptyStringCreation
\f1\i0  method implements the test's action, which is simply creating a string, and returns the output of the action. This output is then taken by UITK and passed to the test's verification method - 
\f2\i verifyTestEmptyStringCreation:
\f1\i0 . The verification method is responsible of determining whether the output of the action is correct or not, and pass or fail the test accordingly. As you can probably guess, UITK identifies the verification method by its name. A verification method must begin with 'verify' followed by the test's name beginning with a capital letter. A verification method accepts one object argument which is the action's result. The return value of the verification method tells UITK if the test passed, failed or is still waiting for a result (an async test). Internally, the result of verification methods is defined as DPTestStatus, but for synchronized tests BOOL may be used instead for convenience.\
\
The example shown above demonstrated what is called a dedicated verification method, but every test case also has a generic verification method. The generic method is used to verify every test (with object return type) that doesn't have a dedicated verification method. To better understand the concept, let's take a look at another example:\
\
\pard\tx480\pardeftab480\ql\qnatural\pardirnatural

\f3\fs20 \cf2 \CocoaLigature0 @interface\cf0  NSStringTests : DPTestCase\
\cf2 @end\cf0 \
\
\cf2 @implementation\cf0  NSStringTests\
\
- (\cf4 NSString\cf0  *)\cf3 testConstantString\cf0  \{\
	\cf2 return\cf0  \cf7 @"Hello"\cf0 ;\
\}\
\
- (\cf4 NSString\cf0  *)\cf3 testFormatString\cf0  \{\
	\cf2 return\cf0  [\cf4 NSString\cf0  \cf3 stringWithFormat:\cf7 @"%@"\cf0 , \cf7 @"Hello"\cf0 ];\
\}\
\
- (\cf4 NSString\cf0  *)\cf3 testCapitalizedString\cf0  \{\
	\cf2 return\cf0  [\cf7 @"hello"\cf0  \cf3 capitalizedString\cf0 ];\
\}\
\
- (DPTestStatus)\cf3 verifyResult:\cf0 (\cf2 id\cf0 )result \cf3 ofTest:\cf0 (\cf4 NSString\cf0  *)testName \{\
	\cf8 DPAssert\cf0 ([result \cf3 isKindOfClass:\cf0 [\cf4 NSString\cf0  \cf3 class\cf0 ]],\
			 \cf7 @"The returned string is not an NSString instance"\cf0 );\
	\
	\cf2 return\cf0  [result \cf3 isEqualToString:\cf7 @"Hello"\cf0 ];\
\}\
\
\cf2 @end\cf6 \
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\tx5280\tx5760\tx6240\tx6720\tx7200\tx7680\tx8160\tx8640\tx9120\tx9600\tx10080\tx10560\tx11040\tx11520\tx12000\tx12480\tx12960\tx13440\tx13920\tx14400\tx14880\tx15360\tx15840\tx16320\tx16800\tx17280\tx17760\tx18240\tx18720\tx19200\tx19680\tx20160\tx20640\tx21120\tx21600\tx22080\tx22560\tx23040\tx23520\tx24000\tx24480\tx24960\tx25440\tx25920\tx26400\tx26880\tx27360\tx27840\tx28320\tx28800\tx29280\tx29760\tx30240\tx30720\tx31200\tx31680\tx32160\tx32640\tx33120\tx33600\tx34080\tx34560\tx35040\tx35520\tx36000\tx36480\tx36960\tx37440\tx37920\tx38400\tx38880\tx39360\tx39840\tx40320\tx40800\tx41280\tx41760\tx42240\tx42720\tx43200\tx43680\tx44160\tx44640\tx45120\tx45600\tx46080\tx46560\tx47040\tx47520\tx48000\ql\qnatural\pardirnatural
\cf6 \
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural

\f1\fs24 \cf0 \CocoaLigature1 In this example we have three different tests. They should all return the same result but accomplish their task in different ways. Instead of writing the verification logic in each one (or in dedicated verification methods), we put it in the generic verification method that'll verify all our tests. This way we gain few important benefits. First is code reuse which minimizes the amount of code and prevents accidental typing mistakes we may do by writing the same logic over and over. Second, by separating the verification logic from the test's action we can measure more precisely the time needed for the action itself (see DPTestCase.h for more info about enabling the speed measuring capabilities). Originally, verification methods where created to enable better speed measuring.\
\
The default implementation of 
\f2\i verifyResult:ofTest:
\f1\i0  returns 
\f2\i DPTestPending
\f1\i0 . This means that any test with object return type that don't have a dedicated verification method will be treated as async test. Taking advantage of this, we can write simple UI tests and tests for multi-threaded code. The included SimpleUITest demonstrates how it's done.\
\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural
\cf0 \ul \ulc0 UI Testing\ulnone \
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural
\cf0 \
UI testing is fundamentally different from unit testing. UITestingKit allows you to write tests from the end user's perspective, meaning they know nothing about the internals of the application. Only the visible UI is available to the tests, and only changes in that UI can be checked for correctness. UI tests does not require your app to link with UITK, and in most cases you probably won't need to.\
\
UI tests are made up of two parts. First, is the user operating the application. A user is an instance of the principal class of the tests bundle, and must conform to the 
\f2\i DPUser
\f1\i0  protocol. The user object then does its tasks just like a normal user would. Operating the UI is done using the accessibility API, and therefor any action the user performs will probably result in some accessibility notifications.\
\
With this in mind, enters the second part of UI testing - QA objects. Every tests bundle willing to test UI, has QA objects that are subclasses of 
\f2\i DPQualityAssurance
\f1\i0 . Before UITK starts invoking the user's actions (see DPUser.h), it instantiates all QA classes from 
\f0\b all
\f1\b0  loaded tests modules. The QA objects then monitor the incoming accessibility notifications, and throw an exception if something is not behaving as expected. If no exception was thrown and all users have finished their actions, UI testing passes.\
\
UI testing is done after all unit tests passed. Before UI testing begins, the tested application is restarted so the user objects can assume they work with a fresh instance of the app. With that being said, it's important to remember that QA objects live their life during both unit and UI testing, so they must be satisfied even during unit testing (that might affect the running application in some way).\
\
Working with the C accessibility API is not always fun, so UITK includes an ObjC wrapper around it. Two classes are used for accessibility: DPUIElement that wraps AXUIElement, and DPAccessibilityNotificationCenter for posting and listening to accessibility notifications. UITestingKit also includes a mechanism for naming objects, and exposes the names through the accessibility API. This allows you to more easily find the elements you're looking for in the elements hierarchy. It is implemented as a standalone class called DPNameServer and the implementation is completely self contained. Both the header and the implementation files are included in UITK's resources directory, so simply copy them to your project in order to take advantage of this feature.\
\
For a complete example of UI testing, see the included SimpleBrowser example, which is Apple's SimpleBrowser example (included with the developer tools) modified to include UI tests.\
\
If you use UITestingKit, or you have some comments/suggestions/bug reports/other random thoughts, please drop me a line at ofri [at] dpompa.com.}